<template>
    <div>
        <el-drawer
            :title="`分配【${role.roleName}】的权限`"
            direction="rtl"
            size="400px"
            v-model="visiable"
            :before-close="close"
        >
            <div v-loading="loading" >
                <el-tree
                    ref="treeRef"
                    :data="menuList"
                    :props="{ label: 'meta', children: 'children' }"
                    :default-expand-all="expandAll"
                    :check-strictly="false"
                    :show-checkbox="true"
                    highlight-current
                    node-key="id"
                >
                    <template #default="{ node, data }">
                        <span class="custom-tree-node">
                            <!-- 一、二级菜单显示自定义图标 -->
                             <SvgIcon v-if="[1,2].includes(node.level)" :name="data.meta.icon || 'ele-Menu'" ></SvgIcon>
                             <!-- 三级菜单显示菜单或按钮图标 -->
                            <el-icon v-else >
                                <ele-Menu v-if="data.type == 1" />
                                <ele-SwitchButton v-else-if="data.type == 2" />
                            </el-icon>
                            <span class="pl10" >{{ data.meta.title }}</span>
                        </span>
                    </template>
                </el-tree>
            </div>
            <template #footer>
                <el-button @click="handleCheckAll">全选/不选</el-button>
                <el-button @click="handleExpand">展开/折叠</el-button>
                <el-button type="primary" @click="submitForm">保存</el-button>
                <el-button @click="close">取消</el-button>
            </template>
        </el-drawer>
    </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted, watch, nextTick, toRefs } from 'vue'
import { getList } from '@/api/system/menu'
import { getMenuIdsByRoleId, saveRoleMenu } from '@/api/system/role' 
import { msg, notify } from '@/utils/element'
import type Node from 'element-plus/es/components/tree/src/model/node.mjs'

// 菜单树ref
const treeRef = ref()

// 定义状态
const state = reactive({
    visiable: false,
    loading: false,
    checked: false, // true 全选
    expandAll: false, // true 展开所有
    role: {} as SysRoleType, // 点击的角色
    menuIds: [] as string[], //当前角色拥有的权限id
    menuList: [] as SysMenuType[], // 存储所有菜单
    submitting: false // 正在提交中
})

const { visiable, loading, checked, expandAll, role, menuIds, menuList, submitting } = {...toRefs(state)}

// 导出父组件访问
defineExpose({
    open
})

// 打开窗口
async function open(role: SysRoleType) {
    state.visiable = true
    state.role = role
    // 获取所有菜单
    await loadMenuList()
    // 查询当前角色拥有的权限id
    await loadMenuIds()
    // 勾选角色原拥有的菜单项
    await checkedOldMenuNode()
}

// 关闭窗口
function close() {
    if (state.submitting) return msg('正在提交中，请稍后')
    state.visiable = false
    state.menuIds = []
    state.menuList = []
    state.checked = false
    state.expandAll = false
}

// 获取所有菜单
async function loadMenuList() {
    try {
        state.loading = true
        const { data } = await getList()
        state.menuList = data
    } catch (error) {

    } finally {
        state.loading = false
    }
}

// 查询当前角色拥有的权限id
async function loadMenuIds() {
    try {
        state.loading = true
        const { data } = await getMenuIdsByRoleId(state.role.id)
        state.menuIds = data
    } catch (error) {

    } finally {
        state.loading = false
    }
}

// 回显角色之前拥有的菜单项
function checkedOldMenuNode() {
    nextTick(() => {
        const { menuIds } = state
        menuIds.forEach(id => {
            // 获取节点对象
            const node = treeRef.value.getNode(id)
            // 判断是否为子节点，如果是子节点则勾选，否则不勾选
            if (node && node.isLeaf) {
                treeRef.value.setChecked(node, true)
            }
        })
    })
}

// 全选/不选
function handleCheckAll() {
    state.checked = !state.checked
    // 全选
    if (state.checked) treeRef.value.setCheckedNodes(state.menuList)
    // 不选
    else treeRef.value.setCheckedNodes([])
}

// 展开/折叠
function handleExpand() {
    state.expandAll = !state.expandAll
    changeTreeNodeStatus(treeRef.value.store.root)
}
function changeTreeNodeStatus(node: Node) {
    node.expanded = state.expandAll
    for (let i = 0; i < node.childNodes.length; i++) {
        // 改变节点自身的expanded属性
        node.childNodes[i].expanded = state.expandAll
        // 递归遍历子节点
        if (node.childNodes[i].childNodes.length > 0) {
            changeTreeNodeStatus(node.childNodes[i])
        }
    }
}

// 提交数据
async function submitForm() {
    try {
        state.submitting = true
        // 获取所有被选中的菜单id
        const checkMenuIds = treeRef.value.getCheckedKeys()
        // 获取半选中的菜单id
        const parentIds = treeRef.value.getHalfCheckedKeys()
        // 合并菜单id
        const menuIds = [...checkMenuIds, ...parentIds]
        // 提交数据
        await saveRoleMenu(state.role.id, menuIds)
        notify('分配权限成功', { type: 'success' })
        state.submitting = false
        close()
    } catch (error) {

    } finally {
        state.submitting = false
    }
}
</script>

<style scoped>
.custom-tree-node {
    font-size: 14px;
    flex: 1;
    display: flex;
    align-items: center;
    padding-left: 8px;
}
</style>